home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
gfx
/
misc
/
gnuplot-3.7src.lha
/
gnuplot-3.7src
/
gnuplot-3.7.lha
/
gnuplot-3.7
/
term
/
cgm.trm
< prev
next >
Wrap
Text File
|
1998-12-14
|
40KB
|
1,267 lines
/* Hey Emacs this is -*- C -*-
* $Id: cgm.trm,v 1.16 1998/06/18 14:59:18 ddenholm Exp $
*/
/* GNUPLOT - cgm.trm */
/*[
* Copyright 1998
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted, but not the right to
* distribute the complete modified source code. Modifications are to
* be distributed as patches to the released version. Permission to
* distribute binaries produced by compiling modified sources is granted,
* provided you
* 1. distribute the corresponding source modifications from the
* released version in the form of a patch file along with the binaries,
* 2. add special version identification to distinguish your version
* in addition to the base release version number,
* 3. provide your name and address as the primary contact for the
* support of your modified version, and
* 4. retain our contact information in regard to use of the base
* software.
* Permission to distribute the released version of the source code along
* with corresponding source modifications in the form of a patch file is
* granted with same provisions 2 through 4 for binary distributions.
*
* This software is provided "as is" without express or implied warranty
* to the extent permitted by applicable law.
]*/
/*
* This file is included by ../term.c and ../docs/termdoc.c.
*
* This terminal driver supports:
* Computer Graphics Metafile
*
* TODO
* better control over plot size (never cutting off labels, correct font
* sizes)
* Fix font sizes for portrait orientation
*
* AUTHOR
* Jim Van Zandt <jrv@vanzandt.mv.com>
*
* send your comments or suggestions to (info-gnuplot@dartmouth.edu).
*/
#include "driver.h"
#ifdef TERM_REGISTER
register_term(cgm)
#endif
#ifdef TERM_PROTO
TERM_PUBLIC void CGM_options __PROTO((void));
TERM_PUBLIC void CGM_init __PROTO((void));
TERM_PUBLIC void CGM_reset __PROTO((void));
TERM_PUBLIC void CGM_text __PROTO((void));
TERM_PUBLIC void CGM_graphics __PROTO((void));
TERM_PUBLIC void CGM_move __PROTO((unsigned int x, unsigned int y));
TERM_PUBLIC void CGM_dashed_vector __PROTO((unsigned int ux, unsigned int uy));
TERM_PUBLIC void CGM_solid_vector __PROTO((unsigned int ux, unsigned int uy));
TERM_PUBLIC void CGM_linetype __PROTO((int linetype));
TERM_PUBLIC void CGM_linecolor __PROTO((int color));
TERM_PUBLIC void CGM_dashtype __PROTO((int dashtype));
TERM_PUBLIC void CGM_linewidth __PROTO((double width));
TERM_PUBLIC void CGM_put_text __PROTO((unsigned int x, unsigned int y,
char *str));
TERM_PUBLIC int CGM_text_angle __PROTO((int ang));
TERM_PUBLIC int CGM_justify_text __PROTO((enum JUSTIFY mode));
TERM_PUBLIC void CGM_point __PROTO((unsigned int x, unsigned int y,
int number));
TERM_PUBLIC int CGM_find_font __PROTO((char *font, int numchar));
TERM_PUBLIC int CGM_set_font __PROTO((char *font));
TERM_PUBLIC void CGM_set_pointsize __PROTO((double size));
#define CGM_LARGE 32767
#define CGM_SMALL 32767/18*13 /* aspect ratio 1:.7222 */
#define CGM_MARGIN (CGM_LARGE/180)
/* convert from plot units to pt */
#define CGM_PT ((term->xmax + CGM_MARGIN)/cgm_plotwidth)
#define CGM_LINE_TYPES 9 /* number of line types we support */
#define CGM_COLORS 7 /* number of colors we support */
#define CGM_POINTS 8 /* number of markers we support */
#define CGM_MAX_SEGMENTS 104 /* maximum # polyline coordinates */
#define CGM_VCHAR (CGM_SMALL/360*12)
#define CGM_HCHAR (CGM_SMALL/360*12*5/9)
#define CGM_VTIC (CGM_LARGE/80)
#define CGM_HTIC (CGM_LARGE/80)
#endif
#ifndef TERM_PROTO_ONLY
#ifdef TERM_BODY
/*
* on NeXTstep, id is an identifier (in ObjC) and causes a parse error
* since some asserts below are mistaken as casts. datum is a type
* defined in ndbm.h which also causes a parse error (ndbm.h is
* included as part of appkit.h, I think). Strangely enough, both
* errors only happen with cpp-precomp -smart, not with the regular
* cpp. (AL)
*/
#ifdef NEXT
#define id id_
#define datum datum_
#endif
#include <ctype.h> /* for isspace() */
#ifndef assert
#define assert(x) 0 /* defeat assertions */
#endif
/* uncomment the following to enable assertions for this module only,
regardless of compiler switches */
#ifdef NDEBUG
#define DEFEAT_ASSERTIONS
#endif
#undef NDEBUG
#include <assert.h>
#define CGM_ADJ (sizeof(int)/sizeof(short))
static unsigned int cgm_posx;
static unsigned int cgm_posy;
static unsigned int cgm_linetype = 1;
static unsigned int cgm_dashtype = 0;
static unsigned int cgm_color = 0;
static int cgm_polyline[CGM_MAX_SEGMENTS]; /* stored polyline coordinates */
static int cgm_coords = 0; /* # polyline coordinates saved */
enum JUSTIFY cgm_justify = LEFT;
static int cgm_vert_text = 0; /* text orientation -- nonzero for vertical */
static int cgm_vert_text_requested = 0;
static int cgm_step_sizes[8]; /* array of currently used dash
lengths in plot units */
static int cgm_step_index = 0; /* index into cgm_step_sizes[] */
static int cgm_step = 0; /* amount of current dash not yet
drawn, in plot units */
static int cgm_tic, cgm_tic707, cgm_tic866, cgm_tic500, cgm_tic1241, cgm_tic1077, cgm_tic621; /* marker dimensions */
/* Each font string is preceded by a byte with its length */
static char GPFAR cgm_font_data[] =
{"\
\005Arial\
\014Arial Italic\
\012Arial Bold\
\021Arial Bold Italic\
\013Times Roman\
\022Times Roman Italic\
\020Times Roman Bold\
\027Times Roman Bold Italic\
\011Helvetica\
\005Roman\
"};
/* variables to record the options */
static char cgm_font[32] = "Arial Bold";
static unsigned int cgm_fontsize = 10;
static unsigned cgm_linewidth; /* line width in plot units */
static unsigned cgm_linewidth_pt = 1; /* line width in pt */
static TBOOLEAN cgm_monochrome = FALSE; /* colors enabled? */
static int cgm_plotwidth = 432; /* assumed width of plot in pt. */
static TBOOLEAN cgm_portrait = FALSE; /* portrait orientation? */
static TBOOLEAN cgm_rotate = TRUE; /* text rotation enabled? */
static TBOOLEAN cgm_dashed = TRUE; /* dashed linestyles enabled? */
static TBOOLEAN cgm_winword6_mode = FALSE; /* workaround for WinWord bug? */
/* prototypes for static functions */
static void CGM_flush_polyline __PROTO((void));
static void CGM_flush_polygon __PROTO((void));
static void CGM_write_char_record __PROTO((int class, int cgm_id, int length,
char *data));
static void CGM_write_code __PROTO((int class, int cgm_id, int length));
static void CGM_write_int __PROTO((int value));
static void CGM_write_int_record __PROTO((int class, int cgm_id, int length,
int *data));
static void CGM_write_mixed_record __PROTO((int class, int cgm_id,
int numint, int *int_data,
int numchar, char *char_data));
TERM_PUBLIC void CGM_init()
{
cgm_posx = cgm_posy = 0;
cgm_linetype = 0;
cgm_vert_text = 0;
}
TERM_PUBLIC void CGM_graphics()
{
register struct termentry *t = term;
static int version_data[] = { 1 };
static char GPFAR description_data[] = "Computer Graphics Metafile version of Gnuplot";
static int vdc_type_data[] = { 0 };
static int integer_precision_data[] = { 16 };
static int real_precision_data[] = { 1, 16, 16 };
static int index_precision_data[] = { 16 };
static int color_precision_data[] = { 16 };
static int color_index_precision_data[] = { 16 };
static int maximum_color_index_data_data[] = { CGM_COLORS };
static int scaling_mode_data[] = { 0, 0, 0 };
static int color_value_extent_data[] = { 0, 0, 0, 255, 255, 255 };
static int GPFAR color_table_data[] =
/* for testing
{
8, 0,0,0, 64,64,64, 128,128,128, 196,196,196, 0,255,255, 255,0,255,
255,255,0, 255,255,255
};
*/
{
CGM_COLORS,
0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 0, 255, 0, 255, 0, 255, 255
/* black red green blue yellow magenta cyan */
};
static int color_selection_mode_data[] = { 0 };
static int linewidth_specification_mode_data[] = { 0 };
static int marker_size_specification_mode_data[] = { 0 };
static int vdc_extent_data[] = { 0, 0, 0, 0 };
static int vdc_integer_precision_data[] = { 16 };
static int transparency_data[] = { 0 }; /* text background: 1=transparent */
static int clip_indicator_data[] = { 0 };
/* static int line_color_data[] = { 1 }; */
static int line_type_data[] = { 1 };
static int interior_style_data[] = { 1 }; /* 1=filled */
static int GPFAR elements_list_data[] =
{
0, /* will be set to # elements in this list */
0, 1, /* Begin Metafile */
0, 2, /* End Metafile */
0, 3, /* Begin Picture */
0, 4, /* Begin Picture Body */
0, 5, /* End Picture */
1, 1, /* Metafile Version */
1, 2, /* Metafile Description */
1, 3, /* VDC Type */
1, 4, /* Integer Precision */
1, 5, /* Real Precision */
1, 6, /* Index Precision */
1, 7, /* Color Precision */
1, 8, /* Color Index Precision */
1, 9, /* Maximum Color Index */
2, 1, /* Scaling Mode */
2, 2, /* Color Selection Mode */
2, 3, /* Line Width Specification Mode */
2, 4, /* Marker Size Specification Mode */
2, 6, /* VDC Extent */
3, 1, /* VDC Integer Precision */
3, 4, /* Transparency */
3, 6, /* Clip Indicator */
4, 1, /* Polyline */
4, 3, /* Polymarker */
4, 4, /* Text */
4, 7, /* Polygon */
4, 11, /* Rectangle */
4, 12, /* Circle */
4, 15, /* Circular Arc Center */
4, 16, /* Circular Arc Center Close */
4, 17, /* Ellipse */
4, 18, /* Elliptical Arc */
4, 19, /* Elliptical Arc Close */
5, 2, /* Line Type */
5, 3, /* Line Width */
5, 4, /* Line Color */
5, 6, /* Marker Type */
5, 7, /* Marker Size */
5, 8, /* Marker Color */
5, 10, /* Text Font Index */
5, 14, /* Text Color */
5, 15, /* Character Height */
5, 16, /* Character Orientation */
5, 18, /* Text Alignment */
5, 22, /* Interior Style */
5, 23, /* Fill Color */
5, 24, /* Hatch Index */
6, 1, /* Escape */
7, 2 /* Application Data */
};
/* metafile description (class 1) */
if (!outstr)
CGM_write_char_record(0, 1, 1, outstr);
else
CGM_write_char_record(0, 1, strlen(outstr) + 1, outstr);
CGM_write_int_record(1, 1, 2, version_data);
CGM_write_char_record(1, 2, sizeof(description_data), description_data);
CGM_write_int_record(1, 3, 2, vdc_type_data);
CGM_write_int_record(1, 4, 2, integer_precision_data);
CGM_write_int_record(1, 5, 6, real_precision_data);
CGM_write_int_record(1, 6, 2, index_precision_data);
CGM_write_int_record(1, 7, 2, color_precision_data);
CGM_write_int_record(1, 8, 2, color_index_precision_data);
CGM_write_int_record(1, 9, 2, maximum_color_index_data_data);
CGM_write_int_record(1, 10, sizeof(color_value_extent_data) / CGM_ADJ,
color_value_extent_data);
elements_list_data[0] = (sizeof(elements_list_data) / CGM_ADJ - 2) / 4;
CGM_write_int_record(1, 11, sizeof(elements_list_data) / CGM_ADJ,
elements_list_data);
if (cgm_winword6_mode == FALSE)
CGM_write_char_record(1, 13, strlen(cgm_font_data), cgm_font_data);
/* picture description (classes 2 and 3) */
CGM_write_char_record(0, 3, 8, "PICTURE1");
CGM_write_int_record(2, 1, 6, scaling_mode_data);
CGM_write_int_record(2, 2, 2, color_selection_mode_data);
CGM_write_int_record(2, 3, 2, linewidth_specification_mode_data);
CGM_write_int_record(2, 4, 2, marker_size_specification_mode_data);
vdc_extent_data[2] = t->xmax + CGM_MARGIN;
vdc_extent_data[3] = t->ymax + CGM_MARGIN;
CGM_write_int_record(2, 6, 8, vdc_extent_data);
CGM_write_int_record(3, 1, 2, vdc_integer_precision_data);
CGM_write_int_record(3, 4, sizeof(transparency_data) / CGM_ADJ,
transparency_data);
CGM_write_int_record(3, 6, sizeof(clip_indicator_data) / CGM_ADJ,
clip_indicator_data);
/* picture body (classes 4 and 5) */
CGM_write_int_record(0, 4, 0, NULL);
/* The WinWord 6.0 and PublishIt input
filters seem to mostly ignore the
color table. With the table, WinWord
maps color 7 to black. */
if (!cgm_winword6_mode)
CGM_write_int_record(5, 34, sizeof(color_table_data) / CGM_ADJ,
color_table_data);
CGM_write_int_record(5, 2, sizeof(line_type_data) / CGM_ADJ,
line_type_data);
cgm_linewidth = cgm_linewidth_pt * CGM_PT;
CGM_write_int_record(5, 3, sizeof(cgm_linewidth) / CGM_ADJ,
(int *) &cgm_linewidth);
CGM_linecolor(0);
/* CGM_write_int_record(5, 4, sizeof(line_color_data)/CGM_ADJ, line_color_data); */
CGM_write_int_record(5, 15, 2, (int *) &t->v_char);
CGM_write_int_record(5, 22, 2, interior_style_data);
{
char buf[45];
sprintf(buf, "%.31s,%d", cgm_font, cgm_fontsize);
CGM_set_font(buf);
}
CGM_set_pointsize(pointsize);
}
TERM_PUBLIC int CGM_find_font(font, numchar)
char *font;
int numchar;
{
int font_index = 1;
char *s;
for (s = cgm_font_data; s < cgm_font_data + strlen(cgm_font_data); s += (int) *s + 1) {
/* strnicmp is not standard, but defined by stdfn.c if not available */
if (numchar == (int) *s && strnicmp(font, s + 1, numchar - 1) == 0)
return font_index;
font_index++;
}
return 0;
}
TERM_PUBLIC int CGM_set_font(font)
char *font;
{
register struct termentry *t = term;
int size, font_index;
char *comma;
int sep;
comma = strchr(font, ',');
if (comma == NULL)
return FALSE; /* bad format */
sep = comma - font;
/* find font in font table, or use 1st font */
font_index = CGM_find_font(font, sep);
if (font_index == 0)
font_index = 1;
CGM_write_int_record(5, 10, 2, &font_index);
/* set font size */
size = cgm_fontsize;
sscanf(comma + 1, "%d", &size);
if (sep > 31)
sep = 31;
strncpy(cgm_font, font, sep);
cgm_font[sep] = NUL;
t->v_char = size * CGM_PT;
t->h_char = (t->v_char * 5) / 9;
CGM_write_int_record(5, 15, 2, (int *) &t->v_char);
return TRUE;
}
TERM_PUBLIC void CGM_text()
{
CGM_flush_polyline();
CGM_write_int_record(0, 5, 0, NULL); /* end picture */
CGM_write_int_record(0, 2, 0, NULL); /* end metafile */
}
TERM_PUBLIC void CGM_linetype(linetype)
int linetype;
{
assert(linetype >= -2);
if (linetype == cgm_linetype)
return;
cgm_linetype = linetype;
CGM_linecolor(linetype);
if (cgm_dashed) {
CGM_dashtype(linetype); /* DBT 10-8-98 use dashes */
} else {
/* dashes for gridlines, solid for everything else */
CGM_dashtype(linetype == -1 ? 2 : 0);
}
/* CGM_dashtype(cgm_monochrome ? linetype : 0); first fix, color->no dashes */
/* CGM_dashtype(linetype); orig distribution */
}
TERM_PUBLIC void CGM_linecolor(linecolor)
int linecolor;
{
assert(linecolor >= -2);
linecolor = (linecolor < 1) ? 1 : linecolor % CGM_COLORS + 1;
if (cgm_monochrome || linecolor == cgm_color)
return;
cgm_color = linecolor;
CGM_flush_polyline();
CGM_write_int_record(5, 4, 2, (int *) &cgm_color);
CGM_write_int_record(5, 23, 2, (int *) &cgm_color);
}
TERM_PUBLIC void CGM_linewidth(width)
double width;
{
int new_linewidth;
assert(width >= 1.);
new_linewidth = width * cgm_linewidth_pt * CGM_PT;
if (new_linewidth == cgm_linewidth)
return;
cgm_linewidth = new_linewidth;
CGM_write_int_record(5, 3, sizeof(cgm_linewidth) / CGM_ADJ,
(int *) &cgm_linewidth);
CGM_dashtype(cgm_dashtype); /* have dash lengths recalculated */
}
TERM_PUBLIC void CGM_dashtype(dashtype)
int dashtype;
{
int i, j;
/* Each group of 8 entries in dot_length[] defines a dash
pattern. Entries in each group are alternately length of
whitespace and length of line, in units of 2/3 of the
linewidth. */
static int dot_length[CGM_LINE_TYPES * 8] =
{ /* 0 - solid */
5, 8, 5, 8, 5, 8, 5, 8, /* 1 - dashes */
5, 3, 5, 3, 5, 3, 5, 3, /* 2 - short dashes */
4, 1, 4, 1, 4, 1, 4, 1, /* 3 - dotted */
4, 8, 4, 1, 4, 8, 4, 1, /* 4 - dash-dot */
4, 9, 4, 1, 4, 1, 0, 0, /* 5 - dash-dot-dot */
4, 10, 4, 1, 4, 1, 4, 1, /* 6 - dash-dot-dot-dot */
4, 10, 4, 10, 4, 1, 0, 0, /* 7 - dash-dash-dot */
4, 10, 4, 10, 4, 1, 4, 1}; /* 8 - dash-dash-dot-dot */
assert(dashtype >= -2);
if (dashtype == cgm_dashtype)
return;
cgm_dashtype = dashtype;
CGM_flush_polyline();
if (dashtype >= CGM_LINE_TYPES)
dashtype = dashtype % CGM_LINE_TYPES;
if (dashtype < 1) {
term->vector = CGM_solid_vector;
return;
}
term->vector = CGM_dashed_vector;
/* set up dash dimensions */
j = (dashtype - 1) * 8;
for (i = 0; i < 8; i++, j++) {
if (dot_length[j])
cgm_step_sizes[i] = (dot_length[j] * cgm_linewidth) * 2 / 3;
else
cgm_step_sizes[i] = 0;
}
/* first thing drawn will be a line */
cgm_step = cgm_step_sizes[1];
cgm_step_index = 1;
}
TERM_PUBLIC void CGM_move(x, y)
unsigned int x, y;
{
assert(x < term->xmax && y < term->ymax);
if (x == cgm_posx && y == cgm_posy)
return;
CGM_flush_polyline();
cgm_posx = x;
cgm_posy = y;
}
static void CGM_flush_polyline()
{
if (cgm_coords == 0)
return;
CGM_write_int_record(4, 1, cgm_coords * 2, cgm_polyline);
cgm_coords = 0;
}
static void CGM_write_char_record(class, cgm_id, numbytes, data)
int class, cgm_id, numbytes;
char *data;
{
int pad, padded_length;
static unsigned char flag = 0xff;
char short_len;
pad = 0;
padded_length = numbytes + 1;
if (numbytes >= 255)
padded_length += 2; /* long string */
if (padded_length & 1)
padded_length += pad = 1; /* needs pad */
CGM_write_code(class, cgm_id, padded_length);
short_len = numbytes;
if (numbytes < 255)
fwrite(&short_len, 1, 1, gpoutfile); /* write true length */
else {
fwrite(&flag, 1, 1, gpoutfile);
CGM_write_int(numbytes);
}
fwrite(data, 1, numbytes + pad, gpoutfile); /* write string */
}
static void CGM_write_int_record(class, cgm_id, numbytes, data)
int class, cgm_id, numbytes, *data;
{
int i;
assert((numbytes & 1) == 0);
CGM_write_code(class, cgm_id, numbytes);
numbytes >>= 1;
for (i = 0; i < numbytes; i++)
CGM_write_int(data[i]);
}
static void CGM_write_mixed_record(class, cgm_id, numint, int_data,
numchar, char_data)
int class, cgm_id, numint, *int_data, numchar;
char *char_data;
{
int i, pad, padded_length;
static unsigned char flag = 0xff;
char short_len;
pad = 0;
padded_length = numchar + 1;
if (numchar >= 255)
padded_length += 2; /* long string */
if (padded_length & 1)
padded_length += pad = 1; /* needs pad */
CGM_write_code(class, cgm_id, numint * 2 + padded_length);
for (i = 0; i < numint; i++)
CGM_write_int(int_data[i]); /* write integers */
short_len = numchar;
if (numchar < 255)
fwrite(&short_len, 1, 1, gpoutfile); /* write string length */
else {
fwrite(&flag, 1, 1, gpoutfile);
CGM_write_int(numchar);
}
fwrite(char_data, 1, numchar + pad, gpoutfile); /* write string */
}
/*
Write the code word that starts a CGM record.
bits in code word are as follows...
cccciiiiiiilllll
where
cccc is a 4-bit class number
iiiiiii is a 7-bit ID number
lllll is a 5-bit length (# bytes following the code word, or
31 followed by a word with the actual number)
*/
static void CGM_write_code(class, cgm_id, length)
int class, cgm_id, length;
{
unsigned code;
assert((0 <= class) &&(class <16));
assert((0 <= cgm_id) && (cgm_id < 128));
assert(0 <= length);
if (length < 31) {
code = ((class &0x0f) <<12) |
((cgm_id & 0x7f) << 5) |
((length & 0x1f));
CGM_write_int(code);
} else {
code = ((class &0x0f) <<12) |
((cgm_id & 0x7f) << 5) |
0x1f;
CGM_write_int(code);
CGM_write_int(length);
}
}
static void CGM_write_int(value)
int value;
{
union {
short s;
char c[2];
} u;
#if !defined(DOS16) && !defined(WIN16)
assert(-32768 <= value && value <= 32767);
#endif
u.c[0] = (value >> 8) & 255; /* convert to network order */
u.c[1] = value & 255;
fwrite(&u.s, 1, 2, gpoutfile);
}
/* Draw a dashed line to (ux,uy). CGM has linestyles, but
they are not usable -- at least with the Word for Windows
6.0 filter, where lines of significant width (even 1 pt)
always come out solid. Therefore, we implement dashed
lines here instead. */
TERM_PUBLIC void CGM_dashed_vector(ux, uy)
unsigned int ux, uy;
{
int xa, ya;
int dx, dy, adx, ady;
int dist; /* approximate distance in plot units
from starting point to specified end
point. */
long remain; /* approximate distance in plot units
remaining to specified end point. */
assert(ux < term->xmax && uy < term->ymax);
dx = (ux - cgm_posx);
dy = (uy - cgm_posy);
adx = abs(dx);
ady = abs(dy * 10);
/* using the approximation
sqrt(x**2 + y**2) ~ x + (5*x*x)/(12*y) when x > y.
Note ordering of calculations to avoid overflow on 16 bit
architectures */
if (10 * adx < ady)
dist = (ady / 2 + 25 * adx / ady * adx / 6 * 5) / 5;
else {
if (adx == 0)
return;
dist = (adx * 10 + (ady / 24) * (ady / adx)) / 10;
}
remain = dist;
xa = cgm_posx;
ya = cgm_posy;
while (remain > cgm_step) {
remain -= cgm_step;
if (cgm_step_index & 1)
CGM_solid_vector((int) (ux - (remain * dx) / dist),
(int) (uy - (remain * dy) / dist));
else {
xa = (int) (ux - (remain * dx) / dist);
ya = (int) (uy - (remain * dy) / dist);
CGM_move(xa, ya);
}
if (++cgm_step_index >= 8)
cgm_step_index = 0;
cgm_step = cgm_step_sizes[cgm_step_index];
}
if (cgm_step_index & 1)
CGM_solid_vector(ux, uy);
else
CGM_move(ux, uy);
cgm_step -= (int) remain;
}
TERM_PUBLIC void CGM_solid_vector(ux, uy)
unsigned int ux, uy;
{
assert(ux < term->xmax && uy < term->ymax);
if (ux == cgm_posx && uy == cgm_posy)
return;
if (cgm_coords > CGM_MAX_SEGMENTS - 2) {
CGM_flush_polyline();
cgm_polyline[cgm_coords++] = cgm_posx;
cgm_polyline[cgm_coords++] = cgm_posy + CGM_MARGIN;
} else if (cgm_coords == 0) {
cgm_polyline[cgm_coords++] = cgm_posx;
cgm_polyline[cgm_coords++] = cgm_posy + CGM_MARGIN;
}
cgm_polyline[cgm_coords++] = ux;
cgm_polyline[cgm_coords++] = uy + CGM_MARGIN;
cgm_posx = ux;
cgm_posy = uy;
}
TERM_PUBLIC void CGM_put_text(x, y, str)
unsigned int x, y;
char str[];
{
static int where[3] = { 0, 0, 1 };
int data[4];
char *s = str;
while (*s)
if (!isspace((int) *s++))
goto showit;
return;
showit:
if (cgm_vert_text != cgm_vert_text_requested) {
cgm_vert_text = cgm_vert_text_requested;
if (cgm_vert_text) {
data[0] = -term->v_char;
data[1] = data[2] = 0;
data[3] = term->v_char;
} else {
data[1] = data[2] = term->v_char;
data[0] = data[3] = 0;
}
CGM_write_int_record(5, 16, 8, data);
}
CGM_flush_polyline();
where[0] = x;
where[1] = y + CGM_MARGIN;
CGM_write_mixed_record(4, 4, 3, where, strlen(str), str);
cgm_posx = cgm_posy = -2000;
}
TERM_PUBLIC int CGM_text_angle(ang)
int ang;
{
if (cgm_rotate) {
cgm_vert_text_requested = ang;
return TRUE;
}
return ang ? FALSE : TRUE;
}
TERM_PUBLIC int CGM_justify_text(mode)
enum JUSTIFY mode;
{
static int data[6] = { 1, 3, 0, 0, 0, 0 };
switch (mode) {
case LEFT:
data[0] = 1;
break;
case CENTRE:
data[0] = 2;
break;
case RIGHT:
data[0] = 3;
break;
default:
assert(0);
}
CGM_write_int_record(5, 18, 12, data);
return (TRUE);
}
TERM_PUBLIC void CGM_reset()
{
cgm_posx = cgm_posy = 0;
}
TERM_PUBLIC void CGM_point(x, y, number)
unsigned int x, y;
int number;
{
int old_dashtype;
if (number < 0) { /* draw dot */
CGM_move(x, y);
CGM_solid_vector(x + 1, y);
return;
}
number %= CGM_POINTS;
CGM_flush_polyline();
old_dashtype = cgm_dashtype;
CGM_dashtype(0);
switch (number) {
case 0: /* draw diamond */
CGM_move(x - cgm_tic, y);
CGM_solid_vector(x, y - cgm_tic);
CGM_solid_vector(x + cgm_tic, y);
CGM_solid_vector(x, y + cgm_tic);
CGM_flush_polygon();
break;
case 1: /* draw plus */
CGM_move(x - cgm_tic, y);
CGM_solid_vector(x + cgm_tic, y);
CGM_move(x, y - cgm_tic);
CGM_solid_vector(x, y + cgm_tic);
break;
case 2: /* draw box */
CGM_move(x - cgm_tic707, y - cgm_tic707);
CGM_solid_vector(x + cgm_tic707, y - cgm_tic707);
CGM_solid_vector(x + cgm_tic707, y + cgm_tic707);
CGM_solid_vector(x - cgm_tic707, y + cgm_tic707);
CGM_flush_polygon();
break;
case 3: /* draw X */
CGM_move(x - cgm_tic707, y - cgm_tic707);
CGM_solid_vector(x + cgm_tic707, y + cgm_tic707);
CGM_move(x - cgm_tic707, y + cgm_tic707);
CGM_solid_vector(x + cgm_tic707, y - cgm_tic707);
break;
case 4: /* draw triangle (point up) */
CGM_move(x, y + cgm_tic1241);
CGM_solid_vector(x - cgm_tic1077, y - cgm_tic621);
CGM_solid_vector(x + cgm_tic1077, y - cgm_tic621);
CGM_flush_polygon();
break;
case 5: /* draw star (asterisk) */
CGM_move(x, y - cgm_tic);
CGM_solid_vector(x, y + cgm_tic);
CGM_move(x + cgm_tic866, y - cgm_tic500);
CGM_solid_vector(x - cgm_tic866, y + cgm_tic500);
CGM_move(x + cgm_tic866, y + cgm_tic500);
CGM_solid_vector(x - cgm_tic866, y - cgm_tic500);
break;
case 6: /* draw triangle (point down) */
CGM_move(x, y - cgm_tic1241);
CGM_solid_vector(x - cgm_tic1077, y + cgm_tic621);
CGM_solid_vector(x + cgm_tic1077, y + cgm_tic621);
CGM_flush_polygon();
break;
case 7: /* draw circle (actually, dodecagon)
(WinWord 6 accepts the CGM "circle"
element, but the resulting circle
is not correctly centered!) */
CGM_move(x, y - cgm_tic);
CGM_solid_vector(x + cgm_tic500, y - cgm_tic866);
CGM_solid_vector(x + cgm_tic866, y - cgm_tic500);
CGM_solid_vector(x + cgm_tic, y);
CGM_solid_vector(x + cgm_tic866, y + cgm_tic500);
CGM_solid_vector(x + cgm_tic500, y + cgm_tic866);
CGM_solid_vector(x, y + cgm_tic);
CGM_solid_vector(x - cgm_tic500, y + cgm_tic866);
CGM_solid_vector(x - cgm_tic866, y + cgm_tic500);
CGM_solid_vector(x - cgm_tic, y);
CGM_solid_vector(x - cgm_tic866, y - cgm_tic500);
CGM_solid_vector(x - cgm_tic500, y - cgm_tic866);
CGM_flush_polygon();
break;
}
CGM_dashtype(old_dashtype);
}
TERM_PUBLIC void CGM_set_pointsize(size)
double size;
{
/* Markers were chosen to have approximately equal
areas. Dimensions are as follows, in units of
cgm_tic:
plus, diamond: half height = 1
square, cross: half height = sqrt(1/2) ~ 12/17
triangle: half width = sqrt(sqrt(4/3)) ~ 14/13,
height = sqrt(3*sqrt(4/3)) ~ 54/29
star: half height = 1, half width = sqrt(3/4) ~ 13/15
dodecagon: coordinates of vertices are 0,
sin(30) = 1/2, cos(30) = sqrt(3/4) ~ 13/15, or 1
The fractions are approximates of the equivalent
continued fractions. */
cgm_tic = (size * term->h_tic / 2);
cgm_tic707 = cgm_tic * 12 / 17;
cgm_tic866 = cgm_tic * 13 / 15;
cgm_tic500 = cgm_tic / 2;
cgm_tic1241 = cgm_tic * 36 / 29;
cgm_tic1077 = cgm_tic * 14 / 13;
cgm_tic621 = cgm_tic * 18 / 29;
}
static void CGM_flush_polygon()
{
if (cgm_coords == 0)
return;
CGM_write_int_record(4, 7, cgm_coords * 2, cgm_polyline);
cgm_coords = 0;
}
TERM_PUBLIC void CGM_options()
{
strcpy(cgm_font, "Arial Bold");
cgm_fontsize = 10;
term->v_char = (unsigned int) (cgm_fontsize * CGM_PT);
term->h_char = (unsigned int) (cgm_fontsize * CGM_PT * 5 / 9);
cgm_linewidth_pt = 1;
cgm_monochrome = FALSE;
cgm_plotwidth = 6 * 72;
cgm_portrait = FALSE;
cgm_rotate = TRUE;
cgm_dashed = TRUE;
cgm_winword6_mode = FALSE;
while (!END_OF_COMMAND) {
if (almost_equals(c_token, "p$ortrait")) {
cgm_portrait = TRUE;
c_token++;
continue;
}
if (almost_equals(c_token, "la$ndscape")) {
cgm_portrait = FALSE;
c_token++;
continue;
}
if (almost_equals(c_token, "de$fault")) {
strcpy(cgm_font, "Arial Bold");
cgm_fontsize = 10;
term->v_char = (unsigned int) (cgm_fontsize * CGM_PT);
term->h_char = (unsigned int) (cgm_fontsize * CGM_PT * 5 / 9);
cgm_linewidth_pt = 1;
cgm_monochrome = FALSE;
cgm_plotwidth = 6 * 72;
cgm_portrait = FALSE;
cgm_rotate = TRUE;
cgm_dashed = TRUE;
cgm_winword6_mode = FALSE;
c_token++;
continue;
}
if (almost_equals(c_token, "w$inword6")) {
cgm_winword6_mode = TRUE;
c_token++;
continue;
}
if (almost_equals(c_token, "m$onochrome")) {
cgm_monochrome = TRUE;
c_token++;
continue;
}
if (almost_equals(c_token, "c$olor")
|| almost_equals(c_token, "c$olour")) {
cgm_monochrome = FALSE;
c_token++;
continue;
}
if (almost_equals(c_token, "r$otate")) {
cgm_rotate = TRUE;
c_token++;
continue;
}
if (almost_equals(c_token, "nor$otate")) {
cgm_rotate = FALSE;
c_token++;
continue;
}
if (almost_equals(c_token, "da$shed")) {
cgm_dashed = TRUE;
c_token++;
continue;
}
if (almost_equals(c_token, "s$olid")) {
cgm_dashed = FALSE;
c_token++;
continue;
}
if (almost_equals(c_token, "li$newidth")) {
c_token++;
if (!END_OF_COMMAND) {
struct value a;
cgm_linewidth_pt = (unsigned int) real(const_express(&a));
if (cgm_linewidth_pt > 10000) {
fputs("gnuplot(cgm.trm): linewidth out of range\n", stderr);
cgm_linewidth_pt = 1;
}
}
continue;
}
if (almost_equals(c_token, "wid$th")) {
c_token++;
if (!END_OF_COMMAND) {
struct value a;
cgm_plotwidth = (int) real(const_express(&a));
if (cgm_plotwidth < 0 || cgm_plotwidth > 10000) {
fputs("gnuplot(cgm.trm): width out of range\n", stderr);
cgm_plotwidth = 6 * 72;
}
}
continue;
}
break;
}
if (!END_OF_COMMAND && isstring(c_token)) {
quote_str(cgm_font, c_token, MAX_ID_LEN);
if (CGM_find_font(cgm_font, strlen(cgm_font)) == 0) {
/* insert the font in the font table */
int n;
n = strlen(cgm_font);
if (n + 1 <= sizeof(cgm_font_data) && n <= 255) {
cgm_font_data[0] = n;
strncpy(cgm_font_data + 1, cgm_font, n);
cgm_font_data[n + 1] = 0;
}
}
c_token++;
}
if (!END_OF_COMMAND) {
/* We have font size specified */
struct value a;
cgm_fontsize = (int) real(const_express(&a));
term->v_char = (unsigned int) (cgm_fontsize * CGM_PT);
term->h_char = (unsigned int) (cgm_fontsize * CGM_PT * 5 / 9);
}
if (cgm_portrait) {
term->xmax = CGM_SMALL - CGM_MARGIN;
term->ymax = CGM_LARGE - CGM_MARGIN;
} else {
term->xmax = CGM_LARGE - CGM_MARGIN;
term->ymax = CGM_SMALL - CGM_MARGIN;
}
sprintf(default_font, "%s,%d", cgm_font, cgm_fontsize);
/* default_font holds the font and size set at 'set term' */
sprintf(term_options, "%s %s %s %s %s width %d linewidth %d \"%s\" %d",
cgm_portrait ? "portrait" : "landscape",
cgm_monochrome ? "monochrome" : "color",
cgm_rotate ? "rotate" : "norotate",
cgm_dashed ? "dashed" : "solid",
cgm_winword6_mode ? "winword6" : "",
cgm_plotwidth,
cgm_linewidth_pt,
cgm_font, cgm_fontsize);
}
#ifdef DEFEAT_ASSERTIONS
#define NDEBUG
#include <assert.h>
#undef DEFEAT_ASSERTIONS
#endif /* DEFEAT_ASSERTIONS */
#ifdef NEXT
#undef id
#undef datum
#endif
#endif /* TERM_BODY */
#ifdef TERM_TABLE
TERM_TABLE_START(cgm_driver)
"cgm", "Computer Graphics Metafile",
CGM_LARGE - CGM_MARGIN, CGM_SMALL - CGM_MARGIN, CGM_VCHAR, CGM_HCHAR,
CGM_VTIC, CGM_HTIC, CGM_options, CGM_init, CGM_reset,
CGM_text, null_scale, CGM_graphics, CGM_move, CGM_solid_vector,
CGM_linetype, CGM_put_text, CGM_text_angle,
CGM_justify_text, CGM_point, do_arrow, CGM_set_font,
CGM_set_pointsize,
TERM_BINARY, /* various flags */
NULL, /* after one plot of multiplot */
NULL, /* before subsequent plot of multiplot */
NULL, /* clear part of multiplot */
CGM_linewidth
TERM_TABLE_END(cgm_driver)
#undef LAST_TERM
#define LAST_TERM cgm_driver
#endif /* TERM_TABLE */
#endif /* TERM_PROTO_ONLY */
#ifdef TERM_HELP
START_HELP(cgm)
"1 cgm",
"?commands set terminal cgm",
"?set terminal cgm",
"?set term cgm",
"?terminal cgm",
"?term cgm",
"?cgm",
" The `cgm` terminal generates a Computer Graphics Metafile. This file format",
" is a subset of the ANSI X3.122-1986 standard entitled \"Computer Graphics -",
" Metafile for the Storage and Transfer of Picture Description Information\".",
" Several options may be set in `cgm`.",
"",
" Syntax:",
" set terminal cgm {<mode>} {<color>} {<rotation>} {solid | dashed}",
" {width <plot_width>} {linewidth <line_width>}",
" {\"<font>\"} {<fontsize>}",
"",
" where <mode> is `landscape`, `portrait`, or `default`;",
" <color> is either `color` or `monochrome`; ",
" <rotation> is either `rotate` or `norotate`;",
" `solid` draws all curves with solid lines, overriding any dashed patterns;",
" <plot_width> is the width of the page in points; ",
" <line_width> is the line width in points; ",
" <font> is the name of a font; and ",
" `<fontsize>` is the size of the font in points.",
"",
" By default, `cgm` uses rotated text for the Y axis label.",
"",
" The first six options can be in any order. Selecting `default` sets all",
" options to their default values.",
"",
" Examples:",
" set terminal cgm landscape color rotate dashed width 432 \\",
" linewidth 1 'Arial Bold' 12 # defaults",
" set terminal cgm 14 linewidth 2 14 # wider lines & larger font",
" set terminal cgm portrait 'Times Roman Italic' 12",
" set terminal cgm color solid # no pesky dashes!",
"2 font",
"?commands set terminal cgm font",
"?set terminal cgm font",
"?set term cgm font",
"?cgm font",
" The first part of a Computer Graphics Metafile, the metafile description,",
" includes a font table. In the picture body, a font is designated by an",
" index into this table. By default, this terminal generates a table with",
" the following fonts:",
"@start table - first is interactive cleartext form",
" Arial",
" Arial Italic",
" Arial Bold",
" Arial Bold Italic",
" Times Roman",
" Times Roman Italic",
" Times Roman Bold",
" Times Roman Bold Italic",
" Helvetica",
" Roman",
"#\\begin{tabular}{|ccl|} \\hline",
"#\\multicolumn{2}{|c|}{CGM fonts}\\\\",
"#&Arial&\\\\",
"#&Arial Italic&\\\\",
"#&Arial Bold&\\\\",
"#&Arial Bold Italic&\\\\",
"#&Times Roman&\\\\",
"#&Times Roman Italic&\\\\",
"#&Times Roman Bold&\\\\",
"#&Times Roman Bold Italic&\\\\",
"#&Helvetica&\\\\",
"#&Roman&\\\\",
"%c c l .",
"%@@CGM fonts",
"%_",
"%@@Arial",
"%@@Arial Italic",
"%@@Arial Bold",
"%@@Arial Bold Italic",
"%@@Times Roman",
"%@@Times Roman Italic",
"%@@Times Roman Bold",
"%@@Times Roman Bold Italic",
"%@@Helvetica",
"%@@Roman",
"@end table",
" Case is not distinct, but the modifiers must appear in the above order (that",
" is, not 'Arial Italic Bold'). 'Arial Bold' is the default font.",
"",
" You may also specify a font name which does not appear in the default font",
" table. In that case, a new font table is constructed with the specified",
" font as its only entry. You must ensure that the spelling, capitalization,",
" and spacing of the name are appropriate for the application that will read",
" the CGM file.",
"2 fontsize",
"?commands set terminal cgm fontsize",
"?set terminal cgm fontsize",
"?set term cgm fontsize",
"?cgm fontsize",
" Fonts are scaled assuming the page is 6 inches wide. If the `size` command",
" is used to change the aspect ratio of the page or the CGM file is converted",
" to a different width (e.g. it is imported into a document in which the",
" margins are not 6 inches apart), the resulting font sizes will be different.",
" To change the assumed width, use the `width` option.",
"2 linewidth",
"?commands set terminal cgm linewidth",
"?set terminal cgm linewidth",
"?set term cgm linewidth",
"?cgm linewidth",
" The `linewidth` option sets the width of lines in pt. The default width is",
" 1 pt. Scaling is affected by the actual width of the page, as discussed",
" under the `fontsize` and `width` options",
"2 rotate",
"?commands set terminal cgm rotate",
"?set terminal cgm rotate",
"?set term cgm rotate",
"?cgm rotate",
" The `norotate` option may be used to disable text rotation. For example,",
" the CGM input filter for Word for Windows 6.0c can accept rotated text, but",
" the DRAW editor within Word cannot. If you edit a graph (for example, to",
" label a curve), all rotated text is restored to horizontal. The Y axis",
" label will then extend beyond the clip boundary. With `norotate`, the Y",
" axis label starts in a less attractive location, but the page can be edited",
" without damage. The `rotate` option confirms the default behavior.",
"2 solid",
"?set terminal cgm solid",
"?set term cgm solid",
"?cgm solid",
" The `solid` option may be used to disable dashed line styles in the",
" plots. This is useful when color is enabled and the dashing of the lines",
" detracts from the appearance of the plot. The `dashed` option confirms the",
" default behavior, which gives a different dash pattern to each curve.",
"2 size",
"?commands set terminal cgm size",
"?set terminal cgm size",
"?set term cgm size",
"?scgm size",
" Default size of a CGM page is 32599 units wide and 23457 units high for",
" landscape, or 23457 units wide by 32599 units high for portrait.",
"2 width",
"?commands set terminal cgm width",
"?set terminal cgm width",
"?set term cgm width",
"?cgm width",
" All distances in the CGM file are in abstract units. The application that",
" reads the file determines the size of the final page. By default, the width",
" of the final page is assumed to be 6 inches (15.24 cm). This distance is",
" used to calculate the correct font size, and may be changed with the `width`",
" option. The keyword should be followed by the width in points. (Here, a",
" point is 1/72 inch, as in PostScript. This unit is known as a \"big point\"",
" in TeX.) `gnuplot` arithmetic can be used to convert from other units, as",
" follows:",
" set terminal cgm width 432 # default",
" set terminal cgm width 6*72 # same as above",
" set terminal cgm width 10/2.54*72 # 10 cm wide",
"2 winword6",
"?commands set terminal cgm winword6",
"?set terminal cgm winword6",
"?set term cgm winword6",
"?cgm winword6",
" The default font table was chosen to match, where possible, the default font",
" assignments made by the Computer Graphics Metafile input filter for",
" Microsoft Word 6.0c, although the filter makes available only 'Arial' and",
" 'Times Roman' fonts and their bold and/or italic variants. Other fonts such",
" as 'Helvetica' and 'Roman' are not available. If the CGM file includes a",
" font table, the filter mostly ignores it. However, it changes certain font",
" assignments so that they disagree with the table. As a workaround, the",
" `winword6` option deletes the font table from the CGM file. In this case,",
" the filter makes predictable font assignments. 'Arial Bold' is correctly",
" assigned even with the font table present, which is one reason it was chosen",
" as the default.",
"",
" `winword6` disables the color tables for a similar reason---with the color",
" table included, Microsoft Word displays black for color 7.",
"",
" Linewidths and pointsizes may be changed with `set linestyle`."
END_HELP(cgm)
#endif /* TERM_HELP */